home *** CD-ROM | disk | FTP | other *** search
- // ===========================================================================
- //
- // GSApp.c
- //
- // Copyright (C) 1996 Apple Computer, Inc. All rights reserved.
- //
- // ===========================================================================
-
-
- // ===========================================================================
- // Includes
- // ===========================================================================
-
- #include <stdlib.h>
-
- #if (kQAPlatform == kQAMacOS)
- #include <Memory.h>
- #include <Windows.h>
- #include <Displays.h>
- #include <QuickDraw.h>
- #include <string.h>
- #endif
-
- #include "RAVE.h"
- #include "QD3DAcceleration.h"
-
- #include "GSGameScene.h"
- #include "GSRandomTriMesh.h"
- #include "GSUtilities.h"
- #include "GSError.h"
-
-
- // ===========================================================================
- // Constants
- // ===========================================================================
-
- #define kWindowPercentage 0.75
- #define kMaxWindowNameLength 256
- #define kMaxEngineNameLength 256
- #define kMaxFormatNameLength 10
-
-
- // ===========================================================================
- // Globals
- // ===========================================================================
-
- #if (kQAPlatform == kQAMacOS)
- WindowPtr gWindowPtr = nil;
- #endif
-
- char gEngineName[kMaxEngineNameLength] =
- "<Engine Name Too Long>";
- char gFormatNames[kQAPixel_CL8 + 1][kMaxFormatNameLength] = {
- " : Alpha1",
- " : RGB16",
- " : ARGB16",
- " : RGB32",
- " : ARGB32",
- " : CL4",
- " : CL8"
- };
-
- TQADevice gDevice;
- TQARect gContentRect;
- TGSDrawInfo gDrawInfo;
- Boolean gUsingAppleHardware = false;
-
-
- // ===========================================================================
- // Private Prototypes
- // ===========================================================================
-
- void
- GSInitializeOperatingSystem(void);
-
- void
- GSCleanUpAndQuit(void);
-
- TGSError
- GSCreateWindow(void);
-
- void
- GSClearWindow(void);
-
- void
- GSSetWindowName(
- const char* inWindowName);
-
- TGSError
- GSSetupDrawInfo(void);
-
- TGSError
- GSCreateDrawContext(
- Boolean inUsingAppleHardware);
-
- void
- GSWaitForClick(void);
-
-
- // ===========================================================================
- // main
- // ===========================================================================
- int
- main(void)
- {
- char windowName[kMaxWindowNameLength];
- TGSError gsError;
- TQAImagePixelType format;
-
- // this call enables Apple's QuickDraw3D Hardware Accelerator. since
- // this card is not a fully-compliant RAVE engine, it must be explicitly
- // enabled by any app that wants to use it. otherwise, it will never
- // be returned by calls to QAGetFirstEngine(). the Apple HW Accelerator
- // has a number of limitations which must be handled by any app that
- // makes RAVE calls to it. we handle these limitations by checking
- // which engine is being used when setting up the TGSDrawInfo and when
- // creating the draw context.
- QAEngineEnable(kQAVendor_Apple, kQAEngine_AppleHW);
-
- GSInitializeOperatingSystem();
-
- gsError = GSCreateWindow();
-
- if (gsError != kGSError_None) {
- GSCleanUpAndQuit();
- }
-
- GSClearWindow();
-
- gsError = GSSetupDrawInfo();
-
- if (gsError != kGSError_None) {
- GSCleanUpAndQuit();
- }
-
- for (format = kQAPixel_RGB16; format <= kQAPixel_CL8; format++) {
- // draw the textures and bitmaps in the same format
- gDrawInfo.mTextureFormat = format;
- gDrawInfo.mBitmapFormat = format;
-
- // copy the engine name into the window name string, and then append
- // as much of the format name as will fit
- strncpy(windowName, gEngineName, (kMaxWindowNameLength - 1));
- strncat(windowName, gFormatNames[format],
- (kMaxWindowNameLength - strlen(windowName) - 1));
-
- // set the window's name to the string we just created and then
- // clear the window before we draw the next scene
- GSSetWindowName(windowName);
- GSClearWindow();
-
- // reset the random seed so that the random triangles will appear
- // the same each time we call GSDrawGameScene
- srand(1);
-
- // here's where the scene actually gets called
- gsError = GSDrawGameScene(&gDrawInfo);
-
- // we now exit if we get any error other than one from RAVE. a
- // RAVE error usually means an engine doesn't support a particular
- // texture or bitmap format, so we can ignore it and go on to
- // the next format.
- if (gsError != kGSError_None && gsError != kGSError_RAVE) {
- GSCleanUpAndQuit();
- }
-
- GSWaitForClick();
- }
-
- // now we draw the scene using the bitmap-only format kQAPixel_Alpha1
- gDrawInfo.mTextureFormat = kQAPixel_RGB32;
- gDrawInfo.mBitmapFormat = kQAPixel_Alpha1;
-
- // copy the engine name into the window name string, and then append
- // as much of the format name as will fit
- strncpy(windowName, gEngineName, (kMaxWindowNameLength - 1));
- strncat(windowName, gFormatNames[kQAPixel_Alpha1],
- (kMaxWindowNameLength - strlen(windowName) - 1));
-
- // set the window's name to the string we just created and then
- // clear the window before we draw the next scene
- GSSetWindowName(windowName);
- GSClearWindow();
-
- srand(1);
-
- // here's where the scene actually gets called
- gsError = GSDrawGameScene(&gDrawInfo);
-
- // we now exit if we get any error other than one from RAVE. a
- // RAVE error usually means an engine doesn't support a particular
- // texture or bitmap format, so we can ignore it and go on to
- // the next format.
- if (gsError != kGSError_None && gsError != kGSError_RAVE) {
- GSCleanUpAndQuit();
- }
-
- GSWaitForClick();
-
- for (format = kQAPixel_RGB16; format <= kQAPixel_CL8; format++) {
- gDrawInfo.mTextureFormat = format;
-
- // reset the random seed so that the random triangles will appear
- // the same each time we call GSRandomTriMeshTexture
- srand(1);
-
- // copy the engine name into the window name string, and then append
- // as much of the format name as will fit
- strncpy(windowName, gEngineName, (kMaxWindowNameLength - 1));
- strncat(windowName, gFormatNames[format],
- (kMaxWindowNameLength - strlen(windowName) - 1));
-
- // set the window's name to the string we just created and then
- // clear the window before we draw the next scene
- GSSetWindowName(windowName);
- GSClearWindow();
-
- // here's where the scene actually gets called
- gsError = GSRandomTriMeshTexture(&gDrawInfo);
-
- // we now exit if we get any error other than one from RAVE. a
- // RAVE error usually means an engine doesn't support a particular
- // texture or bitmap format, so we can ignore it and go on to
- // the next format.
- if (gsError != kGSError_None && gsError != kGSError_RAVE) {
- GSCleanUpAndQuit();
- }
-
- GSWaitForClick();
- }
-
- GSCleanUpAndQuit();
- }
-
-
- // ===========================================================================
- // GSInitializeOperatingSystem
- // ===========================================================================
- void
- GSInitializeOperatingSystem(void)
- {
- #if (kQAPlatform == kQAMacOS)
- MaxApplZone();
-
- MoreMasters();
- MoreMasters();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitWindows();
- InitCursor();
-
- FlushEvents(everyEvent, 0);
- #endif
- }
-
-
- // ===========================================================================
- // GSCleanUpAndQuit
- // ===========================================================================
- void
- GSCleanUpAndQuit(void)
- {
- if (gDrawInfo.mContext != nil) {
- // now that we're finished rendering into the draw context, we
- // delete it, so the engine can free up that memory
- QADrawContextDelete(gDrawInfo.mContext);
- }
-
- #if (kQAPlatform == kQAMacOS)
- if (gWindowPtr != nil) {
- DisposeWindow(gWindowPtr);
- }
- #endif
-
- exit(0);
- }
-
-
- // ===========================================================================
- // GSCreateWindow
- // ===========================================================================
- TGSError
- GSCreateWindow(void)
- {
- #if (kQAPlatform == kQAMacOS)
- GDHandle deepestGDevice = nil;
- Rect displayRect, windowRect;
- long displayWidth, displayHeight, windowSideLength;
-
- // find the screen with the greatest number of colors
- deepestGDevice = GSFindDeepestMacDisplay();
- GSAssert_(deepestGDevice);
-
- // since this is Mac code, we use a GDevice as the RAVE device
- gDevice.deviceType = kQADeviceGDevice;
- gDevice.device.gDevice = deepestGDevice;
-
- displayRect = (**deepestGDevice).gdRect;
-
- displayWidth = displayRect.right - displayRect.left;
- displayHeight = displayRect.bottom - displayRect.top;
-
- // size the window according to the size of the display
- windowSideLength = (displayHeight < displayWidth) ? displayHeight : displayWidth;
- windowSideLength = (long) (windowSideLength * kWindowPercentage);
-
- windowRect.left = displayRect.left + ((displayWidth - windowSideLength) / 2);
- windowRect.top = displayRect.top + ((displayHeight - windowSideLength) / 2);
-
- windowRect.right = windowRect.left + windowSideLength;
- windowRect.bottom = windowRect.top + windowSideLength;
-
- // the window rect is in global coordinates, but the TQARect which is
- // used to create a draw context must be in device-local coordinates,
- // so calculate the window's position based on the upper-left corner
- // of the display it is on.
- gDrawInfo.mContextRect.left = windowRect.left - displayRect.left;
- gDrawInfo.mContextRect.right = windowRect.right - displayRect.left;
- gDrawInfo.mContextRect.top = windowRect.top - displayRect.top;
- gDrawInfo.mContextRect.bottom = windowRect.bottom - displayRect.top;
-
- // create a new color window, with no grow, zoom or close boxes
- gWindowPtr = NewCWindow(nil, &windowRect, "\p", true, noGrowDocProc,
- nil, false, nil);
-
- if (gWindowPtr == nil) {
- return kGSError_OS;
- }
- #endif
-
- return kGSError_None;
- }
-
-
- // ===========================================================================
- // GSClearWindow
- // ===========================================================================
- void
- GSClearWindow(void)
- {
- #if (kQAPlatform == kQAMacOS)
- GrafPtr savedPort;
-
- // remember the current port
- GetPort(&savedPort);
-
- // erase the content area of our window
- SetPort(gWindowPtr);
- EraseRect(&gWindowPtr->portRect);
-
- // reset the previous port
- SetPort(savedPort);
- #endif
- }
-
-
- // ===========================================================================
- // GSSetWindowName
- // ===========================================================================
- void
- GSSetWindowName(
- const char* inWindowName)
- {
- #if (kQAPlatform == kQAMacOS)
- Str255 pascalWindowName;
- short windowNameLength = 0;
-
- windowNameLength = strlen(inWindowName);
-
- // convert the incoming C string to a Pascal string
- BlockMoveData(inWindowName, &pascalWindowName[1], windowNameLength);
-
- // set the length of the Pascal string
- pascalWindowName[0] = windowNameLength;
-
- // set the window's title
- SetWTitle(gWindowPtr, pascalWindowName);
- #endif
- }
-
-
- // ===========================================================================
- // GSSetupDrawInfo
- // ===========================================================================
- TGSError
- GSSetupDrawInfo(void)
- {
- long vendorID = 0, engineID = 0, engineNameLength = 0;
- Boolean usingAppleHardware = false;
- TGSError gsError;
- TQAError qaError;
-
- // find the first engine which is best suited to the device we'll be
- // drawing on
- gDrawInfo.mEngine = QADeviceGetFirstEngine(&gDevice);
-
- if (gDrawInfo.mEngine == nil) {
- return kGSError_RAVE;
- }
-
- // get the length of the engine's name
- qaError = QAEngineGestalt(gDrawInfo.mEngine, kQAGestalt_ASCIINameLength, &engineNameLength);
-
- if (qaError != kQANoErr) {
- return kGSError_RAVE;
- }
-
- if (engineNameLength < kMaxEngineNameLength) {
- // the engine's name will fit into our buffer, so get it
- qaError = QAEngineGestalt(gDrawInfo.mEngine, kQAGestalt_ASCIIName, &gEngineName);
-
- if (qaError != kQANoErr) {
- return kGSError_RAVE;
- }
- }
-
- // use the TQADevice we set up in GSCreateWindow
- gDrawInfo.mDevice = gDevice;
-
- // you can change the format of the textures by uncommenting a different
- // line below. note that if you choose CL4 or CL8, you must set
- // mTextureMakeMipMap to false, because the GSPicture object cannot
- // currently mipmap color-lookup table textures. also, GSPicture does
- // not do a good job converting 32-bit PICTs with alpha channels
- // into CL4 or CL8 textures.
- // gDrawInfo.mTextureFormat = kQAPixel_RGB16;
- // gDrawInfo.mTextureFormat = kQAPixel_ARGB16;
- // gDrawInfo.mTextureFormat = kQAPixel_RGB32;
- // gDrawInfo.mTextureFormat = kQAPixel_ARGB32;
- // gDrawInfo.mTextureFormat = kQAPixel_CL4;
- gDrawInfo.mTextureFormat = kQAPixel_CL8;
-
- // the textures will not be locked or mipmapped
- gDrawInfo.mTextureFlags = kQATexture_None;
-
- // we do not want them to be detached or mipmapped
- gDrawInfo.mTextureDetach = false;
- gDrawInfo.mTextureMakeMipMap = false;
-
- gDrawInfo.mTextureMakeBlackTransparent = true;
- gDrawInfo.mTextureUseTransparentIndex = false;
-
- // you can change the format of the bitmaps by uncommenting a different
- // line below. note that if you use RGB16 or RGB32, the transparent
- // areas of the bitmaps will be opaque, since RAVE ignores the alpha
- // values in those two modes. also, GSPicture does not do a good job
- // converting 32-bit PICTs with alpha channels into CL4 or CL8 bitmaps.
- // gDrawInfo.mBitmapFormat = kQAPixel_Alpha1;
- // gDrawInfo.mBitmapFormat = kQAPixel_RGB16;
- // gDrawInfo.mBitmapFormat = kQAPixel_ARGB16;
- // gDrawInfo.mBitmapFormat = kQAPixel_RGB32;
- // gDrawInfo.mBitmapFormat = kQAPixel_ARGB32;
- // gDrawInfo.mBitmapFormat = kQAPixel_CL4;
- gDrawInfo.mBitmapFormat = kQAPixel_CL8;
-
- // the bitmaps will not be locked or detached
- gDrawInfo.mBitmapFlags = kQABitmap_None;
- gDrawInfo.mBitmapDetach = false;
-
- // we want the black background of the bitmaps to be transparent if
- // we're using one of the ARGB formats, and we want the first color in
- // the color table to be transparent if we're using a CL format.
- gDrawInfo.mBitmapMakeBlackTransparent = true;
- gDrawInfo.mBitmapUseTransparentIndex = true;
-
-
- qaError = QAEngineGestalt(gDrawInfo.mEngine, kQAGestalt_EngineID, &engineID);
-
- if (qaError != kQANoErr) {
- return kGSError_RAVE;
- }
-
- // we're only interested in special-casing Apple's first hardware card
- gUsingAppleHardware = (vendorID == kQAVendor_Apple && engineID == kQAEngine_AppleHW);
-
- if (gUsingAppleHardware) {
- // we are using the Apple Hardware Accelerator, which is not a
- // RAVE-compliant engine. therefore we have to change a few things
- // to handle its idiosyncracies.
- //
- // the Apple HW Accelerator requires that all textures submitted to
- // it be mipmapped. if you want the textures to be in kQAPixel_CL8
- // or kQAPixel_CL4 format, then you must set this field to false,
- // since the TGSImage object currently cannot mipmap textures in
- // color table format. this means you cannot use color table
- // textures with the Apple HW Accelerator (which currently cannot
- // handle them anyway).
- gDrawInfo.mTextureMakeMipMap = true;
-
- // the previous line will cause the TGSImage object to be mipmapped.
- // the next line contains the flags which are passed to QATextureNew
- // so that the call will know the textures have been mipmapped.
- gDrawInfo.mTextureFlags |= kQATexture_Mipmap;
-
- // the Apple HW also requires that all textures be in RGB32 format
- gDrawInfo.mTextureFormat = kQAPixel_RGB32;
-
- // the only bitmap format that the Apple HW can handle is Alpha1
- gDrawInfo.mBitmapFormat = kQAPixel_Alpha1;
- }
-
- gsError = GSCreateDrawContext(gUsingAppleHardware);
-
- if (gsError != kGSError_None) {
- return gsError;
- }
-
- return kGSError_None;
- }
-
-
- // ===========================================================================
- // GSCreateDrawContext
- // ===========================================================================
- TGSError
- GSCreateDrawContext(
- Boolean inUsingAppleHardware)
- {
- TQAError qaError;
-
- gDrawInfo.mContextFlags = kQAContext_None;
-
- // you can make the draw context be double-buffered by uncommenting the
- // following line. when a context is double-buffered, you won't see
- // anything until the entire scene is drawn, at which point everything
- // will appear.
- // gDrawInfo.mContextFlags |= kQAContext_DoubleBuffer;
-
- if (inUsingAppleHardware) {
- // Apple's HW Accelerator requires all draw contexts to have the
- // kQAContext_DeepZ flag set
- gDrawInfo.mContextFlags |= kQAContext_DeepZ;
- }
-
- qaError = QADrawContextNew(&gDrawInfo.mDevice, &gDrawInfo.mContextRect, nil,
- gDrawInfo.mEngine, gDrawInfo.mContextFlags, &gDrawInfo.mContext);
-
- if (qaError != kQANoErr) {
- return kGSError_RAVE;
- }
-
- // once you've created the draw context, there are a number of state
- // variables which can be set, such as the background color, turning
- // antialiasing on and off, etc. below we set some of these if we
- // are using the Apple HW Accelerator.
- if (inUsingAppleHardware) {
- // we turn on the Perspective Z flag so that Apple's HW will
- // perspective-correct the textures. the Apple Software drawing
- // engine always does perspective-correction.
- QASetInt(gDrawInfo.mContext, kQATag_PerspectiveZ, kQAPerspectiveZ_On);
-
- // Apple's HW also requires the optional texture mapping operation
- // state variable to be set a certain way
- QASetInt(gDrawInfo.mContext, kQATag_TextureOp,
- kQATextureOp_Modulate & kQATextureOp_Highlight);
- }
-
- return kGSError_None;
- }
-
-
- // ===========================================================================
- // GSWaitForClick
- // ===========================================================================
- void
- GSWaitForClick(void)
- {
- #if (kQAPlatform == kQAMacOS)
- EventRecord theEvent;
-
- while (!Button())
- GetNextEvent(everyEvent, &theEvent);
-
- while(Button())
- ;
-
- FlushEvents(everyEvent, 0);
- #endif
- }
-
-
-